//Type utilities
//$Id: type_util.h 207 2009-09-17 16:09:26Z Oleg.Bulychov $
#pragma once
#ifndef TYPE_UTIL_H
#define TYPE_UTIL_H

#include <functional>
#include <typeinfo>
//__________________________________________________________________________________
namespace meta
{
//__________________________________________________________________________________
template<typename T>
struct is_class
{
private:
    struct true_t { char dummy[1]; };
    struct false_t { char dummy[2]; };
    template< typename C > static true_t test(int C::*);
    template< typename C > static false_t test(...);
public:

    enum { result = (sizeof(test<T>(0)) == sizeof(true_t)) };
};
//_______________________________________________________________________________
template<>
struct is_class<void>
{
    enum { result = false };
};
//__________________________________________________________________________________
template<int i>
struct int2type
{
    enum { result = i };
};
//__________________________________________________________________________________
template<typename T>
struct type2type
{
    typedef T result;
};
//__________________________________________________________________________________
template<bool flag, typename T, typename U>
struct bool2type
{
    typedef T result;
};
template<typename T, typename U>
struct bool2type<false, T, U>
{
    typedef U result;
};
//__________________________________________________________________________________
template<typename T>
struct is_array
{
    enum {result = 0};
};
template<typename T, size_t N>
struct is_array<T[N]>
{
    enum
    {
        result = 1,
        array_size = N
    };
};
template<typename T>
struct is_array<T[]>
{
    enum
    {
        result = 1,
        array_size = 0
    };
};
//__________________________________________________________________________________
template<typename T>
struct is_pointer
{
    enum {result = 0};
};
template<typename T>
struct is_pointer<T*>
{
    enum {result = 1};
};
//__________________________________________________________________________________
/*
template<typename T>
inline int Is_Pointer(T& t)
{
    return is_pointer<T>::result;
}
template<typename T>
inline int Is_Array(T& t)
{
    return is_array<T>::result;
}
*/
//__________________________________________________________________________________
template<typename T, typename U>
struct is_same_type
{
    enum { result = 0 };
};
template<typename T>
struct is_same_type<T, T>
{
    enum { result = 1 };
};
//__________________________________________________________________________________
struct type_info_less:
    public std::binary_function<std::type_info const*, std::type_info const*, bool>
{
    bool operator()(std::type_info const* left, std::type_info const* right) const
    {
        return left->before(*right) != 0;
    }
};
//_______________________________________________________________________________
template<typename T>
struct is_integral_type
{
    enum {result = 0};
};
//__________________________________________________________________________________
template<> struct is_integral_type<bool>
{ enum {result = 1}; };
template<> struct is_integral_type<char>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned char>
{ enum {result = 1}; };
template<> struct is_integral_type<short>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned short>
{ enum {result = 1}; };
template<> struct is_integral_type<int>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned int>
{ enum {result = 1}; };
template<> struct is_integral_type<long>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned long>
{ enum {result = 1}; };
template<> struct is_integral_type<float>
{ enum {result = 1}; };
template<> struct is_integral_type<double>
{ enum {result = 1}; };

//TODO review: where long != int64_t?
//LLP64 vs LP64
#if defined(_WIN32)
template<> struct is_integral_type<int64_t>
{ enum {result = 1}; };
template<> struct is_integral_type<uint64_t>
{ enum {result = 1}; };
#endif
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
}//meta
#endif
//EOF!
